package com.mcc.collect.opc.bootstrap;

import com.mcc.collect.config.GlobalVar;
import com.mcc.collect.opc.service.IOpcUAClientService;
import com.mcc.common.config.ProjectConfig;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;

@Service
@Slf4j
public class OpcUAClientRunner {

    @Autowired
    private IOpcUAClientService opcUAClientService;

    private OpcUaClient opcUaClient;

    public void run() {
        opcUAClientService.readConfig();
        if (ProjectConfig.getOpcEnabled()) {
            log.info("开始创建OPC UA");
            try {
                // 创建OPC UA客户端
                opcUaClient = createClient();

                //订阅变量
                opcUAClientService.run(opcUaClient);
            } catch (Throwable t) {
                log.error("OPC UA客户端错误: {}", t.getMessage());
                reconnect();
            }
        }
    }

    public void reconnect() {
        try {
            //重连
            System.out.println("重连");
            Thread.sleep(5000);
            run();
        } catch (Exception e) {
//            e.printStackTrace();
            log.error(e.getMessage());
        }
    }

    public OpcUaClient getClient() {
        if (!GlobalVar.initOpc) return null;
        try {
            if (opcUaClient != null) return opcUaClient;
            else return createClient();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public OpcUaClient createClient() throws Exception {
        Path securityTempDir = Paths.get(System.getProperty("java.io.tmpdir"), "security");
        Files.createDirectories(securityTempDir);
        if (!Files.exists(securityTempDir)) {
            throw new Exception("不能够创建安全路径: " + securityTempDir);
        }

//        KeyStoreLoader loader = new KeyStoreLoader().load(securityTempDir);

        return OpcUaClient.create(
                opcUAClientService.getEndpointUrl(),
                endpoints ->
                        endpoints.stream()
                                .filter(opcUAClientService.endpointFilter())
                                .findFirst(),
                configBuilder ->
                        configBuilder
                                .setApplicationName(LocalizedText.english("milo opc-ua client"))//应用名称
                                .setApplicationUri("urn:milo:client")
//                                .setCertificate(loader.getClientCertificate())//证书
//                                .setKeyPair(loader.getClientKeyPair())//密钥对
                                .setIdentityProvider(opcUAClientService.getIdentityProvider())//认证方式
                                .setRequestTimeout(uint(5000))//请求超时时间
                                .build()
        );
    }
}
